package com.atguigu.gmall.pms.service.impl;

import com.atguigu.gmall.pms.entity.*;
import com.atguigu.gmall.pms.entity.vo.SkuVo;
import com.atguigu.gmall.pms.entity.vo.SpuAttrValueVo;
import com.atguigu.gmall.pms.entity.vo.SpuVo;
import com.atguigu.gmall.pms.mapper.*;
import com.atguigu.gmall.pms.service.*;
import com.atguigu.gmall.sms.api.GmallSmsApi;
import com.atguigu.gmall.sms.vo.SkuSaleVo;
import io.jsonwebtoken.lang.Collections;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.gmall.common.bean.PageResultVo;
import com.atguigu.gmall.common.bean.PageParamVo;


@Service("spuService")
public class SpuServiceImpl extends ServiceImpl<SpuMapper, SpuEntity> implements SpuService {
    @Autowired
    private SpuDescService spuDescService;
    @Autowired
    private SpuAttrValueService spuAttrValueService;
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private SkuImagesService skuImagesService;
    @Autowired
    private SkuAttrValueService skuAttrValueService;
    @Autowired
    GmallSmsApi gmallSmsClient;

    @Autowired
    private RabbitTemplate rabbitTemplate;



    @Override
    public PageResultVo queryPage(PageParamVo paramVo) {
        IPage<SpuEntity> page = this.page(
                paramVo.getPage(),
                new QueryWrapper<SpuEntity>()
        );

        return new PageResultVo(page);
    }

    @Override
    public PageResultVo querySpuByCid(Long cid, PageParamVo paramVo) {
       /* QueryWrapper<SpuEntity> queryWrapper = new QueryWrapper<>();
        if (cid!=0){
            //查本类
            queryWrapper.eq("category_id", cid);
        }
        if ()*/
        QueryWrapper<SpuEntity> queryWrapper = new QueryWrapper<>();
        String key = paramVo.getKey();
        if (cid != 0) {
            //查本类
            queryWrapper.eq("category_id", cid);
        }
        //查询商品的id 或者商品名字
        if (StringUtils.isNotBlank(key)) {
//            queryWrapper.eq("id",key).or().like("name", key);
            queryWrapper.and(n -> n.eq("id", key).or().like("name", key));
        }

        IPage<SpuEntity> page = this.page(
                paramVo.getPage(),
                queryWrapper
        );

        return new PageResultVo(page);


    }

    /**
     * 根据Vo类保存新增商品数据
     * 由于保存Sku需要SpuId主键属性，所以需要Spu表保存完之后再保存sku Spu仅一条数据，所以Sku不能在Spu内一起保存
     * Sku 有多条记录，所以营销信息
     *
     * @param spuVo
     */
    @GlobalTransactional
    @Override
    public void saveSpu(SpuVo spuVo){
        //1 保存Spu数据
        //1.1 保存Spu表基础数据 返回主键id用于下方表格复用
        // 保存创建时间和修改时间，由于前端不会传递这两个属性，需要后端生成
        saveSp(spuVo);
        Long spuVoId = spuVo.getId(); // 返回主键SpuId

        //1.2 保存Spu_desc描述信息表（Spu的图片集等大数据字段）
        //通过stream流的方式将Vo类转为Entity类
//        saveSpuDesc(spuVo, spuVoId);
        //这里的this指的是当前对象 虽然controller中注入的service对象是代理对象，代理对象只是对被代理对象的封装
        // 在被代理对象中的this仍然指的是被代理对象本身
        this.spuDescService.saveSpuDesc(spuVo,spuVoId);

//            int i = 1/0;
//        TimeUnit.SECONDS.sleep(11);

        //1.3 保存Spu_Attr_value 基本参数属性表  SpuAttrValueEntity
//        List<SpuAttrValueVo> baseAttrs = spuVo.getBaseAttrs();  据此发现保存集合需要将集合遍历并一一赋值过于麻烦，使用自定义方法更加便捷
        saveSpuAttrValue(spuVo, spuVoId);

        //2 保存Sku数据
        List<SkuVo> skus = spuVo.getSkus();
        if (Collections.isEmpty(skus)) {
            return;
        }
        //2.1 保存sku的基本信息及默认图片 由于有多个sku信息，每个sku信息对应着图片表及属性表，均需要对应的skuId ,批量保存不能获得
        this.saveSku(spuVo, spuVoId, skus);

        // rabbitMQ 保存成功后向search 工程发送消息队列  SpuId 消息越短越好  search 服务根据SpuId从数据库查询最新数据设置到es中
        this.rabbitTemplate.convertAndSend("PMS_ITEM_EXCHANGE","pms.spuSave",spuVoId);


    }

    private void saveSku(SpuVo spuVo, Long spuVoId, List<SkuVo> skus) {
        skus.forEach(sku -> {
            //设置前端未传的数据
            sku.setBrandId(spuVo.getBrandId());
            sku.setSpuId(spuVoId);
            sku.setCategoryId(spuVo.getCategoryId());
            //保存默认图片
            List<String> images = sku.getImages();
            if (!Collections.isEmpty(images)) {
                //保存图片集合的第一个元素 如果前端传递了默认图片，使用默认图片，否则使用第一张图片
                sku.setDefaultImage(sku.getDefaultImage() == null ? images.get(0) : sku.getDefaultImage());
            }
            this.skuMapper.insert(sku);
            //返回sku_id 主键
            Long skuId = sku.getId();

            //2.2 保存sku_images表信息  SkuI   Url图片数据集 一个sku有多张图片使用批量存储
            /*
            skuImagesEntity.setSkuId(skuId);
            skuImagesEntity.setUrl(StringUtils.join(images, ","));*/
            List<SkuImagesEntity> skuImagesEntitys = images.stream().map(image -> {
                SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                skuImagesEntity.setSkuId(skuId);
                skuImagesEntity.setUrl(image);
                //如果当前图片地址和默认图片地址一样则设置为1，否则为0
                skuImagesEntity.setDefaultStatus(image.equals(sku.getDefaultImage()) ? 1 : 0);
                return skuImagesEntity;
            }).collect(Collectors.toList());
            this.skuImagesService.saveBatch(skuImagesEntitys);

            //2.3 保存sku_attr_values表格信息 的销售属性
            List<SkuAttrValueEntity> saleAttrs = sku.getSaleAttrs();
            //前端未传送数据保存
            saleAttrs.forEach(skuAttrValueEntity -> {
                skuAttrValueEntity.setSkuId(skuId);
            });
            this.skuAttrValueService.saveBatch(saleAttrs);

        //3 保存营销数据  需要远程调用SMS模块
            // 3.1 保存 sku_bounds 数据
            SkuSaleVo skuSaleVo = new SkuSaleVo();
            BeanUtils.copyProperties(sku, skuSaleVo);
            skuSaleVo.setSkuId(skuId);
            this.gmallSmsClient.saleSave(skuSaleVo);
        });
    }

    private void saveSpuAttrValue(SpuVo spuVo, Long spuVoId) {
        List<SpuAttrValueVo> baseAttrs = spuVo.getBaseAttrs();
        //调用saveBatch插入（批量）实体类对象集合，通过流map将Vo类转为实体类，同时完成Spu_id 的复制
        spuAttrValueService.saveBatch(baseAttrs.stream().map(baseAttr -> {
            SpuAttrValueEntity spuAttrValueEntity = new SpuAttrValueEntity();
            BeanUtils.copyProperties(baseAttr, spuAttrValueEntity);
            spuAttrValueEntity.setSpuId(spuVoId);
            return spuAttrValueEntity;
        }).collect(Collectors.toList()));
    }



    private void saveSp(SpuVo spuVo) {
        spuVo.setCreateTime(new Date());
        spuVo.setUpdateTime(spuVo.getCreateTime());//保证二者时间相同
        this.save(spuVo);
    }

}